package com.atguigu.gulimail.product.service.impl;

import com.atguigu.gulimail.product.service.CategoryBrandRelationService;
import com.atguigu.gulimail.product.web.Vo.Catelog2Vo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimail.product.dao.CategoryDao;
import com.atguigu.gulimail.product.entity.CategoryEntity;
import com.atguigu.gulimail.product.service.CategoryService;
import org.springframework.transaction.annotation.Transactional;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    CategoryBrandRelationService categoryBrandRelationService;

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<CategoryEntity> listWithTree() {
        //1.查询所有分类数据
        List<CategoryEntity> categoryEntities = baseMapper.selectList(null);
        //2.组装成树形结构
        //2.1找出所有一级分类
        List<CategoryEntity> root=categoryEntities.stream().filter((categoryEntity) -> {
            return categoryEntity.getParentCid()==0;

        }).map((list)->{
            list.setChildData(getChild(categoryEntities,list));
            return list;

        }).sorted((category1,category2)->{ //对子分类进行排序,按照Sort属性

            return (category1.getSort()==null? 0:category1.getSort())-(category2.getSort()==null? 0:category2.getSort());

        }).collect(Collectors.toList());


        return root;
    }

    @Caching(
            evict = {
                    @CacheEvict(value = "catelog",key = "'getLevelOneCategorys'"),
                    @CacheEvict(value = "catelog",key = "'getCatalogJson'"),
            }
    )
    @Transactional
    @Override
    public void updateByIdAndUpdateOther(CategoryEntity category) {
        this.updateById(category);

        if(StringUtils.isNotEmpty(category.getName())){
            categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
        }
        //TODO 同步更新其他于品牌相关连的表

    }

    @Override
    public List<Long> findCatelogPath(Long catelogId) {
        List<Long> path=new ArrayList<>();
        while (catelogId!=0){
            path.add(catelogId);
            catelogId=this.getById(catelogId).getParentCid();
        }
        Collections.reverse(path);
        return path;
    }

    @Cacheable(value = {"catelog"},key = "#root.method.name")
    @Override
    public List<CategoryEntity> getLevelOneCategorys() {
        LambdaQueryWrapper<CategoryEntity> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(CategoryEntity::getParentCid,0);

        List<CategoryEntity> list = this.list(lambdaQueryWrapper);
        return list;
    }


    public List<CategoryEntity> getParentCate(List<CategoryEntity> list,Long parentId){
        List<CategoryEntity> parentList = list.stream().filter(item -> item.getParentCid() == parentId).collect(Collectors.toList());
        return parentList;
    }


//    public Map<String, List<Catelog2Vo>> getRedissonLock(){
//
//        RLock lock = redissonClient.getLock("catelogMap-lock");
//        lock.lock();
//
//        try{
//            ValueOperations<String, String> ops = redisTemplate.opsForValue();
//
//        }finally {
//            lock.unlock();
//        }
//    }
    /**
     * 缓存里的数据如何和数据库保持一致
     * 1》。双写模式：同时修改mysql，redis   会产生脏写问题；
     * 2》。失效模式：mysql改完，删除redis数据，等待下次主动查询；
     * @return
     */
    @Cacheable(value = "catelog",key = "#root.method.name")
    @Override
    public Map<String, List<Catelog2Vo>> getCatalogJson() {

        List<CategoryEntity> list = baseMapper.selectList(null);

        //所有一级分类
        List<CategoryEntity> oneLelvelCate = getParentCate(list, 0L);

        Map<String, List<Catelog2Vo>> collect = oneLelvelCate.stream().collect(Collectors.toMap(k -> k.getCatId().toString()
            ,v->{
                List<CategoryEntity> one_TwoCate = getParentCate(list, v.getCatId());
                if(one_TwoCate!=null){
                    List<Catelog2Vo> collect2 = one_TwoCate.stream().map(two -> {
                        Catelog2Vo catelog2Vo = new Catelog2Vo();
                        catelog2Vo.setId(two.getCatId().toString());
                        catelog2Vo.setName(two.getName());
                        catelog2Vo.setCatalog1Id(v.getCatId().toString());

                        List<CategoryEntity> threeCate = getParentCate(list, two.getCatId());
                        if (threeCate != null) {
                            List<Catelog2Vo.Catelog3Vo> collect3 = threeCate.stream().map(three -> {
                                Catelog2Vo.Catelog3Vo catelog3Vo = new Catelog2Vo.Catelog3Vo();
                                catelog3Vo.setCatalog2Id(two.getCatId().toString());
                                catelog3Vo.setName(three.getName());
                                catelog3Vo.setId(three.getCatId().toString());
                                return catelog3Vo;
                            }).collect(Collectors.toList());

                            catelog2Vo.setCatalog3List(collect3);
                            return catelog2Vo;
                        }
                        return null;
                    }).collect(Collectors.toList());
                    return collect2;
                }
                return null;
            }));

        return collect;

    }

    public List<CategoryEntity> getChild(List<CategoryEntity> allList,CategoryEntity rootCategory){

        List<CategoryEntity> childList = allList.stream().filter(categoryEntity ->
                //找到子分类
                        Objects.equals(categoryEntity.getParentCid(), rootCategory.getCatId()))
                        .map((item)->{
                            item.setChildData(getChild(allList,item));
                            return item;
                            //对子分类排序
                        }).sorted((category1,category2)->{
                            return (category1.getSort()==null? 0:category1.getSort())-(category2.getSort()==null? 0:category2.getSort());
                }).collect(Collectors.toList());

        return childList;
    }

}